module FdHash where

import FdType
import FdUtil
import FdHelper

import Data.List
import Data.IORef
import Monad
import Control.Monad.Error

-- type HashRef = IORef [(Id, Val)]
--

fd_new_hash :: [(Val, Val)] -> Fineday Val
fd_new_hash vals = do {
    hash <- makeHash vals;
    return $ Hash $ hash;
} 

fd_nil_hash = fd_new_hash []

fd_get_hash_elem :: [Val] -> Fineday Val
fd_get_hash_elem [Hash hs, k] = do {
    res <- getHashItem hs k;
    return (case res of 
        Just elem -> elem
        Nothing   -> Nil);
}
fd_get_hash_elem paras = throwError $ ParamErr (length paras) 2

fd_set_hash_elem :: [Val] -> Fineday Val 
fd_set_hash_elem [Hash hs, key, val] = setHashItem hs key val
fd_set_hash_elem paras               = throwError $ ParamErr (length paras) 2

---
--

makeHash :: [(Val, Val)] -> Fineday HashRef
makeHash pairs = io $ newIORef pairs

getHashItem :: HashRef -> Val -> Fineday (Maybe Val)
getHashItem hsRef id = do {
	hash <- io $ readIORef hsRef;
	return $ lookup id hash;
}

setHashItem :: HashRef -> Val -> Val -> Fineday Val
setHashItem hsRef id val = do {
	hash <- io $ readIORef hsRef;
	hash <- return $ filter (\(_id, _) -> _id/=id) hash;
	io $ writeIORef hsRef ((id, val): hash);
	return $ Hash $ hsRef;
}

removeHashItem :: HashRef -> Val -> Fineday Val
removeHashItem hsRef id = do {
	io $ modifyIORef hsRef (\hash ->
		filter (\(_id, _) -> _id/=id) hash	
	);
	return $ Hash $ hsRef;
}

